package nirvana.core.validation;

import jakarta.validation.Valid;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
 * ValidatorList
 *
 * @author linkanyway
 * @version 1.0
 * @date 2022/05/30 20:04
 */
public class ValidatorList<T> implements List<T> {

    /**
     * inner list
     *
     * @description valid annotation support nested validate
     */
    @Valid
    private List<T> list;


    /**
     * constructor
     */
    public ValidatorList() {
        this.list = new ArrayList<> ();
    }


    /**
     * constructor
     *
     * @param list list parameter
     */
    public ValidatorList(List<T> list) {
        this.list = list;
    }

    /**
     * get the list
     *
     * @return List
     */
    public List<T> getList() {
        return list;
    }

    /**
     * set the list
     */
    public void setList(List<T> list) {
        this.list = list;
    }


    /**
     * Returns the number of elements in this list. If this list contains more than Integer.MAX_VALUE elements,
     * returns Integer.MAX_VALUE.
     * Returns:
     * the number of elements in this list
     *
     * @return size
     */
    @Override
    public int size() {
        return list.size ();
    }

    /**
     * Returns true if this list contains no elements.
     * Returns:
     * true if this list contains no elements
     */
    @Override
    public boolean isEmpty() {
        return list.isEmpty ();
    }

    /**
     * Returns true if this list contains the specified element. More formally, returns true if and only if this list
     * contains at least one element e such that (o==null ? e==null : o.equals(e)).
     * Params:
     * o – element whose presence in this list is to be tested
     * Returns:
     * true if this list contains the specified element
     * Throws:
     * ClassCastException – if the type of the specified element is incompatible with this list (optional)
     * NullPointerException – if the specified element is null and this list does not permit null elements (optional)
     */
    @Override
    public boolean contains(Object o) {
        return list.contains (o);
    }


    /**
     * Returns an iterator over the elements in this list in proper sequence.
     * Returns:
     * an iterator over the elements in this list in proper sequence
     */
    @Override
    public Iterator<T> iterator() {
        return list.iterator ();
    }


    /**
     * Returns an array containing all the elements in this list in proper sequence (from first to last element).
     * The returned array will be "safe" in that no references to it are maintained by this list. (In other words,
     * this method must allocate a new array even if this list is backed by an array). The caller is thus free to
     * modify the returned array.
     * This method acts as bridge between array-based and collection-based APIs.
     * Returns:
     * an array containing all the elements in this list in proper sequence
     * See Also:
     * Arrays.asList(Object[])
     */
    @Override
    public Object[] toArray() {
        return list.toArray ();
    }

    /**
     * Returns an array containing all the elements in this list in proper sequence (from first to last element);
     * the runtime type of the returned array is that of the specified array. If the list fits in the specified
     * array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified
     * array and the size of this list.
     * If the list fits in the specified array with room to spare (i.e., the array has more elements than the list),
     * the element in the array immediately following the end of the list is set to null. (This is useful in
     * determining the length of the list only if the caller knows that the list does not contain any null elements.)
     * Like the toArray() method, this method acts as bridge between array-based and collection-based APIs. Further,
     * this method allows precise control over the runtime type of the output array, and may, under certain
     * circumstances, be used to save allocation costs.
     * Suppose x is a list known to contain only strings. The following code can be used to dump the list into a
     * newly allocated array of String:
     * String[] y = x.toArray(new String[0]);
     * Note that toArray(new Object[0]) is identical in functionName to toArray().
     * Params:
     * a – the array into which the elements of this list are to be stored, if it is big enough; otherwise, a new
     * array of the same runtime type is allocated for this purpose.
     * Returns:
     * an array containing the elements of this list
     * Throws:
     * ArrayStoreException – if the runtime type of the specified array is not a supertype of the runtime type of
     * every element in this list
     * NullPointerException – if the specified array is null
     */
    @Override
    public <T> T[] toArray(T @NotNull [] para) {
        return list.toArray (para);
    }

    /**
     * add element
     * <p>
     * Appends the specified element to the end of this list (optional operation).
     * Lists that support this operation may place limitations on what elements may be added to this list. In
     * particular, some lists will refuse to add null elements, and others will impose restrictions on the type of
     * elements that may be added. List classes should clearly specify in their documentation any restrictions on
     * what elements may be added.
     * Params:
     * e – element to be appended to this list
     * Returns:
     * true (as specified by Collection. Add)
     * Throws:
     * UnsupportedOperationException – if the add operation is not supported by this list
     * ClassCastException – if the class of the specified element prevents it from being added to this list
     * NullPointerException – if the specified element is null and this list does not permit null elements
     * IllegalArgumentException – if some property of this element prevents it from being added to this list
     */
    @Override
    public boolean add(T e) {
        return list.add (e);
    }


    /**
     * Removes the first occurrence of the specified element from this list, if it is present (optional operation).
     * If this list does not contain the element, it is unchanged. More formally, removes the element with the lowest
     * index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists). Returns true if
     * this list contained the specified element (or equivalently, if this list changed as a result of the call).
     * Params:
     * o – element to be removed from this list, if present
     * Returns:
     * true if this list contained the specified element
     * Throws:
     * ClassCastException – if the type of the specified element is incompatible with this list (optional)
     * NullPointerException – if the specified element is null and this list does not permit null elements (optional)
     * UnsupportedOperationException – if the remove operation is not supported by this list
     */
    @Override
    public boolean remove(Object o) {
        return list.remove (o);
    }

    /**
     * Returns true if this list contains all the elements of the specified collection.
     * Params:
     * c – collection to be checked for containment in this list
     * Returns:
     * true if this list contains all the elements of the specified collection
     * Throws:
     * ClassCastException – if the types of one or more elements in the specified collection are incompatible with
     * this list (optional)
     * NullPointerException – if the specified collection contains one or more null elements and this list does not
     * permit null elements (optional), or if the specified collection is null
     * See Also:
     * contains(Object)
     */
    @Override
    public boolean containsAll(@NotNull Collection<?> c) {
        return list.containsAll (c);
    }

    /**
     * Appends all the elements in the specified collection to the end of this list, in the order that they are
     * returned by the specified collection's iterator (optional operation). The behavior of this operation is
     * undefined if the specified collection is modified while the operation is in progress. (Note that this will
     * occur if the specified collection is this list, and it's nonempty.)
     * Params:
     * c – collection containing elements to be added to this list
     * Returns:
     * true if this list changed as a result of the call
     * Throws:
     * UnsupportedOperationException – if the addAll operation is not supported by this list
     * ClassCastException – if the class of an element of the specified collection prevents it from being added to
     * this list
     * NullPointerException – if the specified collection contains one or more null elements and this list does not
     * permit null elements, or if the specified collection is null
     * IllegalArgumentException – if some property of an element of the specified collection prevents it from being
     * added to this list
     * See Also:
     * add(Object)
     */
    @Override
    public boolean addAll(@NotNull Collection<? extends T> c) {
        return list.addAll (c);
    }

    /**
     * Appends all the elements in the specified collection to the end of this list, in the order that they are
     * returned by the specified collection's iterator (optional operation). The behavior of this operation is
     * undefined if the specified collection is modified while the operation is in progress. (Note that this will
     * occur if the specified collection is this list, and it's nonempty.)
     * Params:
     * c – collection containing elements to be added to this list
     * Returns:
     * true if this list changed as a result of the call
     * Throws:
     * UnsupportedOperationException – if the addAll operation is not supported by this list
     * ClassCastException – if the class of an element of the specified collection prevents it from being added to
     * this list
     * NullPointerException – if the specified collection contains one or more null elements and this list does not
     * permit null elements, or if the specified collection is null
     * IllegalArgumentException – if some property of an element of the specified collection prevents it from being
     * added to this list
     * See Also:
     * add(Object)
     */
    @Override
    public boolean addAll(int index, @NotNull Collection<? extends T> c) {
        return list.addAll (c);
    }

    /**
     * Removes from this list all of its elements that are contained in the specified collection (optional operation).
     * Params:
     * c – collection containing elements to be removed from this list
     * Returns:
     * true if this list changed as a result of the call
     * Throws:
     * UnsupportedOperationException – if the removeAll operation is not supported by this list
     * ClassCastException – if the class of an element of this list is incompatible with the specified collection
     * (optional)
     * NullPointerException – if this list contains a null element and the specified collection does not permit null
     * elements (optional), or if the specified collection is null
     * See Also:
     * remove(Object), contains(Object)
     */
    @Override
    public boolean removeAll(@NotNull Collection<?> c) {
        return list.removeAll (c);
    }

    /**
     * Removes from this list all of its elements that are contained in the specified collection (optional operation).
     * Params:
     * c – collection containing elements to be removed from this list
     * Returns:
     * true if this list changed as a result of the call
     * Throws:
     * UnsupportedOperationException – if the removeAll operation is not supported by this list
     * ClassCastException – if the class of an element of this list is incompatible with the specified collection
     * (optional)
     * NullPointerException – if this list contains a null element and the specified collection does not permit null
     * elements (optional), or if the specified collection is null
     * See Also:
     * remove(Object), contains(Object)
     */
    @Override
    public boolean retainAll(@NotNull Collection<?> c) {
        return list.removeAll (c);
    }

    /**
     * Removes all the elements from this list (optional operation). The list will be empty after this call returns.
     * Throws:
     * UnsupportedOperationException – if the clear operation is not supported by this list
     */
    @Override
    public void clear() {
        list.clear ();
    }

    /**
     * Returns the element at the specified position in this list.
     * Params:
     * index – index of the element to return
     * Returns:
     * the element at the specified position in this list
     * Throws:
     * IndexOutOfBoundsException – if the index is out of range (index < 0 || index >= size())
     */
    @Override
    public T get(int index) {
        return list.get (index);
    }

    /**
     * Replaces the element at the specified position in this list with the specified element (optional operation).
     * Params:
     * index – index of the element to replace
     * element – element to be stored at the specified position
     * Returns:
     * the element previously at the specified position
     * Throws:
     * UnsupportedOperationException – if the set operation is not supported by this list
     * ClassCastException – if the class of the specified element prevents it from being added to this list
     * NullPointerException – if the specified element is null and this list does not permit null elements
     * IllegalArgumentException – if some property of the specified element prevents it from being added to this list
     * IndexOutOfBoundsException – if the index is out of range (index < 0 || index >= size())
     */
    @Override
    public T set(int index, T element) {
        return list.set (index, element);
    }

    /**
     * Inserts the specified element at the specified position in this list (optional operation). Shifts the element
     * currently at that position (if any) and any subsequent elements to the right (adds one to their indices).
     * Params:
     * index – index at which the specified element is to be inserted
     * element – element to be inserted
     * Throws:
     * UnsupportedOperationException – if the add operation is not supported by this list
     * ClassCastException – if the class of the specified element prevents it from being added to this list
     * NullPointerException – if the specified element is null and this list does not permit null elements
     * IllegalArgumentException – if some property of the specified element prevents it from being added to this list
     * IndexOutOfBoundsException – if the index is out of range (index < 0 || index > size())
     */
    @Override
    public void add(int index, T element) {
        list.add (index, element);
    }

    /**
     * Removes the element at the specified position in this list (optional operation). Shifts any subsequent
     * elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
     * Params:
     * index – the index of the element to be removed
     * Returns:
     * the element previously at the specified position
     * Throws:
     * UnsupportedOperationException – if the remove operation is not supported by this list
     * IndexOutOfBoundsException – if the index is out of range (index < 0 || index >= size())
     */
    @Override
    public T remove(int index) {
        return list.remove (index);
    }

    /**
     * Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not
     * contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals
     * (get(i))), or -1 if there is no such index.
     * Params:
     * o – element to search for
     * Returns:
     * the index of the first occurrence of the specified element in this list, or -1 if this list does not contain
     * the element
     * Throws:
     * ClassCastException – if the type of the specified element is incompatible with this list (optional)
     * NullPointerException – if the specified element is null and this list does not permit null elements (optional)
     */
    @Override
    public int indexOf(Object o) {
        return list.indexOf (o);
    }

    /**
     * Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not
     * contain the element. More formally, returns the highest index i such that (o==null ? get(i)==null : o.equals
     * (get(i))), or -1 if there is no such index.
     * Params:
     * o – element to search for
     * Returns:
     * the index of the last occurrence of the specified element in this list, or -1 if this list does not contain
     * the element
     * Throws:
     * ClassCastException – if the type of the specified element is incompatible with this list (optional)
     * NullPointerException – if the specified element is null and this list does not permit null elements (optional)
     */
    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf (o);
    }

    /**
     * Returns a list iterator over the elements in this list (in proper sequence).
     * Returns:
     * a list iterator over the elements in this list (in proper sequence
     */
    @Override
    public ListIterator<T> listIterator() {
        return list.listIterator ();
    }

    /**
     * Returns a list iterator over the elements in this list (in proper sequence), starting at the specified
     * position in the list. The specified index indicates the first element that would be returned by an initial
     * call to next. An initial call to previous would return the element with the specified index minus one.
     * Params:
     * index – index of the first element to be returned from the list iterator (by a call to next)
     * Returns:
     * a list iterator over the elements in this list (in proper sequence), starting at the specified position in the
     * list
     * Throws:
     * IndexOutOfBoundsException – if the index is out of range (index < 0 || index > size()
     */
    @Override
    public ListIterator<T> listIterator(int index) {
        return list.listIterator (index);
    }


    /**
     * Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
     * (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so
     * non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list
     * supports all the optional list operations supported by this list.
     * This method eliminates the need for explicit range operations (of the sort that commonly exist for arrays).
     * Any operation that expects a list can be used as a range operation by passing a subList view instead of a
     * whole list. For example, the following idiom removes a range of elements from a list:
     * list.subList(from, to).clear();
     * Similar idioms may be constructed for indexOf and lastIndexOf, and all the algorithms in the Collections
     * class can be applied to a subList.
     * The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is
     * structurally modified in any way other than via the returned list. (Structural modifications are those that
     * change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield
     * incorrect results.)
     * Params:
     * fromIndex – low endpoint (inclusive) of the subList
     * toIndex – high endpoint (exclusive) of the subList
     * Returns:
     * a view of the specified range within this list
     * Throws:
     * IndexOutOfBoundsException – for an illegal endpoint index value (fromIndex < 0 || toIndex > size || fromIndex
     * > toIndex)
     */
    @Override
    public List<T> subList(int fromIndex, int toIndex) {
        return list.subList (fromIndex, toIndex);
    }
}
